KM.InputsManager = function( iDomElement, iCamera )
{
    this._domElement = iDomElement;
    this._camera = iCamera;
    
    this._isMouseDown = false;
    
    this._oldMousePosition = vec3.create( [ 0, 0, 0 ] );
    this._currentMousePosition = vec3.create( [ 0, 0, 0 ] );
    this._diffMousePosition = vec3.create( [ 0, 0, 0 ] );
    
    this._verticalRotationAngle = 0;
    this._horizontalRotationAngle = 0;
};

KM.InputsManager.LOG = false;

KM.InputsManager.prototype.constructor = KM.InputsManager;

KM.InputsManager.prototype.bind = function()
{
    this._domElement.addEventListener( 'mousedown', this.onMouseDown.bind( this ), false );
    this._domElement.addEventListener( 'mouseup', this.onMouseUp.bind( this ), false );
    this._domElement.addEventListener( 'mousemove', this.onMouseMove.bind( this ), false );
    this._domElement.addEventListener( 'mousewheel', this.onMouseWheel.bind( this ), false );
};

KM.InputsManager.prototype.onMouseDown = function( iEvent )
{
    this._isMouseDown = true;
    
    KM.InputsManager.GetMousePositionOnDomElement( iEvent, this._domElement, this._oldMousePosition );
    
    if( KM.InputsManager.LOG ) console.log("InputsManager.js, onMouseDown() : " + vec3.str( this._oldMousePosition ));
};

KM.InputsManager.prototype.onMouseUp = function( iEvent )
{
    this._isMouseDown = false;
    
    if( KM.InputsManager.LOG ) console.log("InputsManager.js, onMouseUp()");
};

KM.InputsManager.prototype.onMouseMove = function( iEvent )
{
    if( !this._isMouseDown ) return;
    
    KM.InputsManager.GetMousePositionOnDomElement( iEvent, this._domElement, this._currentMousePosition );
    vec3.subtract( this._currentMousePosition, this._oldMousePosition, this._diffMousePosition );
    var delta = vec3.create( [ this._diffMousePosition[ 0 ] * -0.005, this._diffMousePosition[ 1 ] * -0.005 ] );
    
    // Compute target to camera vector
    var camPosition = vec3.create( [ this._camera._eye[ 0 ], this._camera._eye[ 1 ], this._camera._eye[ 2 ] ] );
    var targetPosition = vec3.create( [ 0, 0, 0 ] );
    var targetToViewpointVector = vec3.subtract( camPosition, targetPosition, vec3.create() );
    
    // Compute the current horizontal rotation angle <=> theta
    var theta = Math.atan2( targetToViewpointVector[ 0 ], targetToViewpointVector[ 2 ] );
    
    // Compute the current vertical rotation angle <=> phi
    var phi = Math.atan2( Math.sqrt( targetToViewpointVector[ 0 ] * targetToViewpointVector[ 0 ] + targetToViewpointVector[ 2 ] * targetToViewpointVector[ 2 ] ), targetToViewpointVector[ 1 ] );
    
    theta += delta[ 0 ];
    phi += delta[ 1 ];
    
    var EPS = 0.000001;
    phi = Math.max( EPS, Math.min( Math.PI / 2 - EPS, phi ) );
    
    var radius = vec3.length( targetToViewpointVector );
    var eye = this._camera._eye;
    eye[ 0 ] = radius * Math.sin( phi ) * Math.sin( theta );
    eye[ 1 ] = radius * Math.cos( phi );
    eye[ 2 ] = radius * Math.sin( phi ) * Math.cos( theta );
    
    var target = vec3.create( [ 0, 0, 0 ] );
    var up = vec3.create( [ 0, 1, 0 ] );
    
    this._camera.lookAt( eye, target, up );
    
    vec3.set( this._currentMousePosition, this._oldMousePosition );
    
//    if( KM.InputsManager.LOG ) console.log("InputsManager.js, onMouseMove() : " + vec3.str( this._diffMousePosition ));
};

KM.InputsManager.prototype.onMouseWheel = function( iEvent )
{
    iEvent.preventDefault();
    
    var delta = 0;

    if( iEvent.wheelDelta ) // WebKit / Opera / Explorer 9
    { 
        delta = -iEvent.wheelDelta;
    }
    else if( iEvent.detail ) // Firefox
    { 
        delta = iEvent.detail * 10;
    }
    
    delta *= -1;
    delta /= 100;
    
    var eye = vec3.create( [ this._camera._eye[ 0 ], this._camera._eye[ 1 ], this._camera._eye[ 2 ] ] );
    var dir = vec3.create( [ this._camera._dir[ 0 ], this._camera._dir[ 1 ], this._camera._dir[ 2 ] ] );
    dir[ 0 ] *= delta;
    dir[ 1 ] *= delta;
    dir[ 2 ] *= delta;
    
    vec3.add( eye, dir );
    
    var target = vec3.create( [ 0, 0, 0 ] );
    var up = vec3.create( [ 0, 1, 0 ] );
    
    this._camera.lookAt( eye, target, up );
};

KM.InputsManager.GetMousePositionOnDomElement = function( iEvent, iDomElement, oMousePosition )
{
    oMousePosition[ 0 ] = iEvent.pageX - iDomElement.offsetLeft;
    oMousePosition[ 1 ] = iEvent.pageY - iDomElement.offsetTop;
    oMousePosition[ 2 ] = 0;
    
    return oMousePosition;
};